#include "sys.h"
#include "net.h"
#include "log.h"
#include "cJSON.h"
#include "devinfo.h"

int check_gateway_interface(char* ifname)
{
    FILE* fp = NULL;
    char buf[256] = { 0 };
    char* delim = " \t";
    char *iface, *dest;
    int flag = 0;

    fp = fopen(PROC_NET_ROUTE, "r");
    if (!fp) {
        log_error("open " PROC_NET_ROUTE " file error.");
        return flag;
    }

    fgets(buf, sizeof(buf), fp); //skip header
    bzero(buf, sizeof(buf));
    while (fgets(buf, sizeof(buf), fp) != NULL) {
        if (strlen(buf) == 0) {
            continue;
        }
        iface = strtok(buf, delim);
        dest = strtok(NULL, delim);
        if (!strcmp(dest, "00000000")) {
            strcpy(ifname, iface);
            flag = 1;
            break;
        }
        bzero(buf, sizeof(buf));
    }
    fclose(fp);
    return flag;
}
void devinfo_get_addrinfo(DevInfo_t* devinfo)
{
    struct in_addr ip;
    uint8_t mac[6];

    getifaddr(devinfo->ifname, (void*)&ip, "ip");
    getifaddr(devinfo->ifname, mac, "mac");

    strcpy(devinfo->ip, inet_ntoa(ip));
    sprintf(devinfo->mac, "%02x:%02x:%02x:%02x:%02x:%02x", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
}
static char* _cpu_info(char* buf)
{
    char *delim = ":", *ptr;
    ptr = strtok(buf, delim);
    ptr = strtok(NULL, delim);
    ptr[strlen(ptr) - 1] = '\0';
    return ptr;
}
void get_cpu_info(char* cpuinfo)
{
    FILE* fp;
    char buf[128];

    fp = fopen(PROC_CPU_INFO, "r");
    while (fgets(buf, sizeof(buf), fp) != NULL) {
        if (strstr(buf, "Processor")) {
            strcpy(cpuinfo, _cpu_info(buf));
            break;
        } else if (strstr(buf, "model name")) {
            strcpy(cpuinfo, _cpu_info(buf));
        } else if (strstr(buf, "cpu model")) {
            strcpy(cpuinfo, _cpu_info(buf));
        }
    }
}
void get_misc_info(DevInfo_t* devinfo)
{
    struct tm *p, tm_p;
    struct sysinfo s_info;
    time_t now, uptime;

    sysinfo(&s_info);
    now = time(NULL);
    uptime = now - s_info.uptime;
    localtime_r(&uptime, &tm_p);
    p = &tm_p;
    sprintf(devinfo->upTime, "%d-%02d-%02d %02d:%02d:%02d",
        1900 + p->tm_year, 1 + p->tm_mon, p->tm_mday, p->tm_hour, p->tm_min, p->tm_sec);
    strcpy(devinfo->insertTime, devinfo->upTime);
    sprintf(devinfo->mem, "%ld", s_info.totalram / 1024 / 1024);
}
static int check_is_wifi(char* ifname)
{
    return strstr(ifname, "wlan") > 0 ? 1 : 0;
}
void load_devinfo(DevInfo_t* devinfo)
{

Get_gateway_interface:
    if (!check_gateway_interface(devinfo->ifname)) {
        log_warn("Can not get gateway interface, retry...");
        sleep(1);
        goto Get_gateway_interface;
    }
    devinfo->is_wifi = check_is_wifi(devinfo->ifname);
    devinfo_get_addrinfo(devinfo);
#if __ANDROID__
    extern void android_get_devinfo(DevInfo_t*);
    android_get_devinfo(devinfo);
#elif __LINUX_OS__
    extern void linux_get_devinfo(DevInfo_t*);
    linux_get_devinfo(devinfo);
#endif
    get_cpu_info(devinfo->cpu);
    get_misc_info(devinfo);
}

cJSON* devinfo2cjson(DevInfo_t* devinfo, cJSON* root)
{
    cJSON* _root;

    if (!root)
        _root = cJSON_CreateObject();
    else
        _root = root;

    cJSON_AddStringToObject(_root, "clientId", devinfo->mac);
    cJSON_AddStringToObject(_root, "accountCode", devinfo->mac);
    cJSON_AddStringToObject(_root, "stbIp", devinfo->ip);
    // cJSON_AddStringToObject(_root, "wlanNumberIp", "");
    // cJSON_AddStringToObject(_root, "mac2", "");
    cJSON_AddNumberToObject(_root, "netModel", (devinfo->is_wifi ? 1 : 3));
    // cJSON_AddStringToObject(_root, "clientType", devinfo->dev_type);
    cJSON_AddStringToObject(_root, "clientModel", devinfo->model);
    cJSON_AddStringToObject(_root, "clientVersion", devinfo->sw_version);
    cJSON_AddStringToObject(_root, "clientFactory", devinfo->factory);
    cJSON_AddStringToObject(_root, "clientMem", devinfo->mem);
    cJSON_AddStringToObject(_root, "clientCpu", devinfo->cpu);
    cJSON_AddStringToObject(_root, "osType", devinfo->osType);
    cJSON_AddStringToObject(_root, "osVersion", devinfo->osVersion);
    cJSON_AddStringToObject(_root, "upTime", devinfo->upTime);
    cJSON_AddStringToObject(_root, "insertTime", devinfo->insertTime);
    return _root;
}
